#ifndef _LCD_WD2704M_H
#define _LCD_WD2704M_H

/** Beinhaltet einige Funktionen zum Zugriff auf das LCD Modell WD2704M
 *  von Wintek mit zwei HD44780 Kontrollern und 4x27 Zeichen Displayzeilen.
 *
 * (c) Copyright 2007 von Enrico Homann 
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <stdlib.h>

/* #define DEBUG */

/* MCU Frequenz Voreinstellung */
#ifndef F_CPU
#define F_CPU 20.0E6					
#endif

#include <util/delay.h>

#include "lcd_hd44780.h"

/* Boolean definieren */
#ifndef BOOL
#define BOOL
typedef enum { false, true } bool;
#endif

/* RLE Datenmarkierungsbit */
#ifndef RLE_SIGN
#define RLE_SIGN	7		
#endif

/* Anzahl Displayzeilen HD44780 Kontroller */
#define LCD_HD44780_LINES					 2
/* Max. Zeichen pro Zeile */
#define LCD_HD44780_LINEWIDTH					27

#define LCD_WD2704M_MAX_X	LCD_HD44780_LINES - 1
#define LCD_WD2704M_MAX_Y	3


typedef uint8_t lcd27x4frame_t[LCD_WD2704M_MAX_Y][LCD_WD2704M_MAX_X];

typedef struct {

	unsigned char  name[10];			/* Name des Films */
	uint8_t	      frames;				/* Anzahl an Frames */
	uint8_t	      pause_ms;				/* Pause zw. Frames in ms */
	uint8_t		ms_loop;      			/* Anzahl der _delay_ms(pause_ms) Aufrufe */
	
	const lcd27x4frame_t movie[];			/* Framedaten */	

} movie27x4_t;

#ifndef _RLE_ENCODEDMOVIE_T
#define _RLE_ENCODEDMOVIE_T

typedef struct {
	uint8_t	name[10];      		/* Name des Films */
	uint8_t	frames;        		/* Anzahl an Frames */
	uint8_t	pause_ms;      		/* Pause zw. Frames in ms */
	uint8_t	ms_loop;      		/* Anzahl der _delay_ms(pause_ms) Aufrufe */
	uint8_t	x_size;        		/* Spalten */
	uint8_t	y_size;        		/* Zeilen */
	uint16_t 	encoded_size; 	/* Groesse der komprimierten Framedaten */

	const uint8_t movie[];  		/* Array an Komprimierten Framedaten */
} rle_encodedmovie_t;

#endif

#ifndef LCD_WD2704M_CURSOR_POS
#define LCD_WD2704M_CURSOR_POS

struct {
	uint8_t	x, y;			/* Koordinaten */
} lcd_wd2704m_cursor_pos_s;

#endif

#ifdef __cplusplus
extern 'C' {				/* Deklaration zum Einbinden von C Code in C++ */
#endif

/**
 * void lcd_wd2704m_gotoxy ( uint8_t x, uint8_t y )
 **
 * Setzt den DDRAM des zustaendigen Kontrollers entsprechend den x und 
 * y Koordinaten. Liefert den zustaendigen Kontroller zurueck
 **
 * @param x uint8_t x Koordinate
 * @param y uint8_t y Koordinate
 */

uint8_t lcd_wd2704m_gotoxy ( uint8_t x, uint8_t y );

/**
 * void lcd_wd2704m_writestrxy ( uint8_t x, uint8_t y, char *str )
 **
 * Schreibt ein String str an die mit x,y angegebenen Koordinaten
 **
 * @param x uint8_t x Koordinate
 * @param y uint8_t y Koordinate
 * @param str *char String 
 */

extern void lcd_wd2704m_writestrxy ( uint8_t x, uint8_t y, char *str );

/**
 * void lcd_wd2704m_writestrxy ( uint8_t x, uint8_t y, unsigned char str )
 **
 * Schreibt ein Zeichen str an die mit x,y angegebenen Koordinaten
 **
 * @param x uint8_t x Koordinate
 * @param y uint8_t y Koordinate
 * @param str unsigned char Zeichen 
 */

extern void lcd_wd2704m_writechrxy ( uint8_t x, uint8_t y, unsigned char str );

/**
 * void lcd_wd2704m_writechar ( unsigned char str )
 **
 * Schreibt ein Zeichen str an die aktuelle per lcd_wd2704m_curosr_pos
 * angebene Position. (virtuelle DDRAM Position von den zwei Kontrollern)
 **
 * @param str unsigned char Zeichen 
 */

extern void lcd_wd2704m_writechar ( unsigned char chr );

/**
 * void lcd_wd2704m_cleardisplay ()
 **
 * Loescht den DDRAM beider Kontroller
 **
 * @param lcd27x4frame_t frame Arrayfeld
 */

extern void lcd_wd2704m_cleardisplay ();

/**
 * void lcd_wd2704m_command ( uint8_t command )
 **
 * Gibt command als Intruktion an beide Kontroller aus.
 **
 * @param uint8_t command Instruktion
 */

extern void lcd_wd2704m_command ( uint8_t command );

/**
 * void lcd_wd2704m_writeframe27x4_f ( const lcd27x4frame_t frame )
 **
 * Schreibt ein Arrayfeld (27x4) in den LCD DDRAM.
 * Liest aus den Flashspeicher (PROGMEM)!
 **
 * @param lcd27x4frame_t frame Arrayfeld
 */

extern void lcd_wd2704m_writeframe27x4_f ( const lcd27x4frame_t frame  );

/**
 * void lcd_wd2704m_init ( uint8_t fs, uint8_t es, uint8_t ds )
 **
 * Initialisiert beide Kontroller mit 
 * fs = Functionset, es = Entrymodeset, ds = Displayset
 * und initialisiert die virtuelle DDRAM Position 
 **
 * @param uint8_t fs Functionset
 * @param uint8_t es Entrymodeset
 * @param uint8_t ds Displayset
 */
extern void lcd_wd2704m_init ( uint8_t fs, uint8_t es, uint8_t ds );

/**
 * void lcd_wd2704m_gfx_shiftdisplay_cross ( bool e1_right )
 **
 * Spezialgrafik Routine: Laesst den DDRAM beider Kontroller entgegengesetzt
 * nach links bzw rechts verschieben.
 * e1_right = true  -> Kontroller 1 rechts; Kontroller 2 links
 * e1_right = false -> Kontroller 1 links ; Kontroller 2 rechts
 **
 * @param bool e1_right siehe oben
 */

extern void lcd_wd2704m_gfx_shiftdisplay_cross ( bool e1_right );

/**
 * void lcd_wd2704m_gfx_playmovie27x4_f ( const lcd27x4frame_t *m )
 **
 * Schreibt ein Arrayfeld (27x4) in den LCD DDRAM.
 * Liest aus den Flashspeicher (PROGMEM)!
 **
 * @param movie27x_t m Zeiger auf Filmdaten 
 */

extern void lcd_wd2704m_gfx_playmovie27x4_f ( const movie27x4_t *m );

/**
 * void lcd_wd2704m_gfx_playencodedmovie_rle_f ( const rle_encodedmovie_t *m )
 **
 * Spezialgrafik Routine: Spielt den ueber *m angegebenen RLE kodierten Film
 * ab.
 **
 * @param const rle_codedmovie_t *m Zeiger auf Filmdaten
 */

extern void lcd_wd2704m_gfx_playencodedmovie_rle_f ( const rle_encodedmovie_t *m );

#ifdef __cplusplus
}									/* Abschluss der Deklaration zum Einbinden von C Code in C++ */
#endif 

#endif	/* _LCD_WD2704M_H */
